package io.fredia.femicro.admin.biz;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import io.fredia.femicro.admin.constant.AdminCommonConstant;
import io.fredia.femicro.admin.entity.Group;
import io.fredia.femicro.admin.entity.Menu;
import io.fredia.femicro.admin.entity.ResourceAuthority;
import io.fredia.femicro.admin.mapper.GroupMapper;
import io.fredia.femicro.admin.mapper.MenuMapper;
import io.fredia.femicro.admin.mapper.ResourceAuthorityMapper;
import io.fredia.femicro.admin.mapper.UserMapper;
import io.fredia.femicro.admin.vo.AuthorityMenuTree;
import io.fredia.femicro.admin.vo.GroupUsers;
import io.fredia.femicro.cache.annotation.CacheClear;
import io.fredia.femicro.common.biz.BaseBiz;

@Service
@Transactional(rollbackFor = Exception.class)
public class GroupBiz extends BaseBiz<GroupMapper, Group> {
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private ResourceAuthorityMapper resourceAuthorityMapper;
	@Autowired
	private MenuMapper menuMapper;

	@Override
	public void insertSelective(Group entity) {
		if (AdminCommonConstant.ROOT == entity.getParentId()) {
			entity.setPath("/" + entity.getCode());
		} else {
			Group parent = this.selectById(entity.getParentId());
			entity.setPath(parent.getPath() + "/" + entity.getCode());
		}
		super.insertSelective(entity);
	}

	@Override
	public void updateById(Group entity) {
		if (AdminCommonConstant.ROOT == entity.getParentId()) {
			entity.setPath("/" + entity.getCode());
		} else {
			Group parent = this.selectById(entity.getParentId());
			entity.setPath(parent.getPath() + "/" + entity.getCode());
		}
		super.updateById(entity);
	}

	/**
	 * 获取群组关联用户
	 *
	 * @param groupId
	 * @return
	 */
	public GroupUsers getGroupUsers(int groupId) {
		return new GroupUsers(userMapper.selectMemberByGroupId(groupId), userMapper.selectLeaderByGroupId(groupId));
	}

	/**
	 * 变更群主所分配用户
	 *
	 * @param groupId
	 * @param members
	 * @param leaders
	 */
	@CacheClear(pre = "permission")
	public void modifyGroupUsers(int groupId, String members, String leaders) {
		mapper.deleteGroupLeadersById(groupId);
		mapper.deleteGroupMembersById(groupId);
		if (!StringUtils.isEmpty(members)) {
			String[] mem = members.split(",");
			for (String m : mem) {
				mapper.insertGroupMembersById(groupId, Integer.parseInt(m));
			}
		}
		if (!StringUtils.isEmpty(leaders)) {
			String[] mem = leaders.split(",");
			for (String m : mem) {
				mapper.insertGroupLeadersById(groupId, Integer.parseInt(m));
			}
		}
	}

	/**
	 * 变更群组关联的菜单
	 *
	 * @param groupId
	 * @param menus
	 */
	@CacheClear(keys = { "permission:menu", "permission:u" })
	public void modifyAuthorityMenu(int groupId, String[] menus) {
		resourceAuthorityMapper.deleteByAuthorityIdAndResourceType(groupId + "",
				AdminCommonConstant.RESOURCE_TYPE_MENU);
		List<Menu> menuList = menuMapper.selectAll();
		Map<String, String> map = new HashMap<String, String>();
		for (Menu menu : menuList) {
			map.put(menu.getId().toString(), menu.getParentId().toString());
		}
		Set<String> relationMenus = new HashSet<String>();
		relationMenus.addAll(Arrays.asList(menus));
		ResourceAuthority authority = null;
		for (String menuId : menus) {
			findParentID(map, relationMenus, menuId);
		}
		for (String menuId : relationMenus) {
			authority = new ResourceAuthority(AdminCommonConstant.AUTHORITY_TYPE_GROUP,
					AdminCommonConstant.RESOURCE_TYPE_MENU);
			authority.setAuthorityId(groupId + "");
			authority.setResourceId(menuId);
			authority.setParentId("-1");
			resourceAuthorityMapper.insertSelective(authority);
		}
	}

	private void findParentID(Map<String, String> map, Set<String> relationMenus, String id) {
		String parentId = map.get(id);
		if (String.valueOf(AdminCommonConstant.ROOT).equals(id)) {
			return;
		}
		relationMenus.add(parentId);
		findParentID(map, relationMenus, parentId);
	}

	/**
	 * 分配资源权限
	 *
	 * @param groupId
	 * @param menuId
	 * @param elementId
	 */
	@CacheClear(keys = { "permission:ele", "permission:u" })
	public void modifyAuthorityElement(int groupId, int menuId, int elementId) {
		ResourceAuthority authority = new ResourceAuthority(AdminCommonConstant.AUTHORITY_TYPE_GROUP,
				AdminCommonConstant.RESOURCE_TYPE_BTN);
		authority.setAuthorityId(groupId + "");
		authority.setResourceId(elementId + "");
		authority.setParentId("-1");
		resourceAuthorityMapper.insertSelective(authority);
	}

	/**
	 * 移除资源权限
	 *
	 * @param groupId
	 * @param menuId
	 * @param elementId
	 */
	@CacheClear(keys = { "permission:ele", "permission:u" })
	public void removeAuthorityElement(int groupId, int menuId, int elementId) {
		ResourceAuthority authority = new ResourceAuthority();
		authority.setAuthorityId(groupId + "");
		authority.setResourceId(elementId + "");
		authority.setParentId("-1");
		resourceAuthorityMapper.delete(authority);
	}

	/**
	 * 获取群主关联的菜单
	 *
	 * @param groupId
	 * @return
	 */
	public List<AuthorityMenuTree> getAuthorityMenu(int groupId) {
		List<Menu> menus = menuMapper.selectMenuByAuthorityId(String.valueOf(groupId),
				AdminCommonConstant.AUTHORITY_TYPE_GROUP);
		List<AuthorityMenuTree> trees = new ArrayList<AuthorityMenuTree>();
		AuthorityMenuTree node = null;
		for (Menu menu : menus) {
			node = new AuthorityMenuTree();
			node.setText(menu.getTitle());
			BeanUtils.copyProperties(menu, node);
			trees.add(node);
		}
		return trees;
	}

	/**
	 * 获取群组关联的资源
	 *
	 * @param groupId
	 * @return
	 */
	public List<Integer> getAuthorityElement(int groupId) {
		ResourceAuthority authority = new ResourceAuthority(AdminCommonConstant.AUTHORITY_TYPE_GROUP,
				AdminCommonConstant.RESOURCE_TYPE_BTN);
		authority.setAuthorityId(groupId + "");
		List<ResourceAuthority> authorities = resourceAuthorityMapper.select(authority);
		List<Integer> ids = new ArrayList<Integer>();
		for (ResourceAuthority auth : authorities) {
			ids.add(Integer.parseInt(auth.getResourceId()));
		}
		return ids;
	}
}
